const { parse } = require("@vue/component-compiler-utils");
const compilerUtil = require("@vue/component-compiler");
const templateCompiler = require("vue-template-compiler");

const { nextId } = require("./_id");

function getImportName(fullPath) {
  return `tmp://${fullPath}`;
}

function createEntryCode(input) {
  const imports = [];

  input.styles.forEach((style) => {
    imports.push(`import '${getImportName(style.outfile)}'`);
  });
  imports.push(`import TPL from '${getImportName(input.template.outfile)}'`);
  imports.push(`import SCRIPT from '${getImportName(input.script.outfile)}'`);

  return `${imports.join("\n")}
    
export default {...TPL, ...SCRIPT }`;
}

async function transform({ source, filename, tmpFilename, id }) {
  // TODO 移除 @vue/component-compiler-utils/@vue/component-compiler 依赖
  const _descriptor = parse({
    filename,
    source,
    compiler: templateCompiler,
    compilerParseOptions: {},
    needMap: false,
  });

  const descriptor = JSON.parse(JSON.stringify(_descriptor));

  // TODO 移除 @vue/component-compiler-utils/@vue/component-compiler 依赖
  const compiler = compilerUtil.createDefaultCompiler({
    template: { scopeId: `data-v-${id}` },
  });

  const input = {
    template: {},
    script: {},
    styles: [],
  };

  // 处理样式
  if (Array.isArray(descriptor.styles) && descriptor.styles.length > 0) {
    descriptor.styles.forEach((styleBlock) => {
      input.styles.push({
        outfile: `${tmpFilename}__styles_${nextId()}.css`,
        code: styleBlock.content,
        scoped: styleBlock.scoped,
      });
    });
  }

  // 处理模板
  if (descriptor.template) {
    const body = compiler.compileTemplate(filename, descriptor.template);
    const code = `${body.code}
    
const _tpl = {render, staticRenderFns};
export default _tpl;`;
    input.template = {
      outfile: `${tmpFilename}__template.js`,
      code,
    };

    // 处理异常
  }

  // 处理 script
  if (descriptor.script) {
    const code = descriptor.script.content;
    input.script = {
      outfile: `${tmpFilename}__script.js`,
      code,
    };
  }

  const entryFile = {
    code: createEntryCode(input),
    outfile: `${tmpFilename}.js`,
  };

  const result = [entryFile, input.template, input.script, ...input.styles];
  return {
    entry: entryFile.outfile,
    scriptEntry: input.script.outfile,
    templateEntry: input.template.outfile,
    files: result,
  };
}

module.exports = {
  transform,
};
